package helper

// internal/helper/SensitiveHelper.go
import (
	"fmt"
	"strings"
	"unicode/utf8"
)

// PdsBusinessException 自定义异常结构体
type PdsBusinessException struct {
	Code    int
	Message string
}

func (e *PdsBusinessException) Error() string {
	return fmt.Sprintf("Code: %d, Message: %s", e.Code, e.Message)
}

// 定义常量
const (
	EmptyContent   = 10001
	EmptyWordPool  = 10002
	CannotFindFile = 10003
)

// HashMap 模拟 PHP 的 HashMap
type HashMap map[string]interface{}

func (m HashMap) Get(key string) interface{} {
	return m[key]
}

func (m HashMap) Put(key string, value interface{}) {
	m[key] = value
}

// SensitiveHelper 敏感词处理结构体
type SensitiveHelper struct {
	wordTree HashMap
}

// Init 初始化 SensitiveHelper
func (s *SensitiveHelper) Init() *SensitiveHelper {
	s.wordTree = make(HashMap)
	return s
}

// SetTree 构建敏感词树
func (s *SensitiveHelper) SetTree(sensitiveWords []string) (*SensitiveHelper, error) {
	if len(sensitiveWords) == 0 {
		return nil, &PdsBusinessException{Code: EmptyWordPool, Message: "词库不能为空"}
	}
	s.wordTree = make(HashMap)
	for _, word := range sensitiveWords {
		s.buildWordToTree(word)
	}
	return s, nil
}

// buildWordToTree 将单个敏感词构建成树结构
func (s *SensitiveHelper) buildWordToTree(word string) {
	if word == "" {
		return
	}
	tree := s.wordTree
	wordLength := utf8.RuneCountInString(word)
	runes := []rune(word)
	for i := 0; i < wordLength; i++ {
		keyChar := string(runes[i])
		tempTree, ok := tree[keyChar].(HashMap)
		if !ok {
			newTree := make(HashMap)
			newTree.Put("ending", false)
			tree.Put(keyChar, newTree)
			tree = newTree
		} else {
			tree = tempTree
		}
		if i == wordLength-1 {
			tree.Put("ending", true)
		}
	}
}

// GetBadWord 检测文字中的敏感词
func (s *SensitiveHelper) GetBadWord(content string, matchType int, wordNum int) []string {
	contentLength := utf8.RuneCountInString(content)
	badWordList := []string{}
	runes := []rune(content)
	for length := 0; length < contentLength; length++ {
		matchFlag := 0
		flag := false
		tempMap := s.wordTree
		for i := length; i < contentLength; i++ {
			keyChar := string(runes[i])
			nowMap, ok := tempMap[keyChar].(HashMap)
			if !ok {
				break
			}
			tempMap = nowMap
			matchFlag++
			ending, _ := nowMap["ending"].(bool)
			if !ending {
				continue
			}
			flag = true
			if matchType == 1 {
				break
			}
		}
		if !flag {
			matchFlag = 0
		}
		if matchFlag <= 0 {
			continue
		}
		badWord := string(runes[length : length+matchFlag])
		badWordList = append(badWordList, badWord)
		if wordNum > 0 && len(badWordList) == wordNum {
			return badWordList
		}
		length = length + matchFlag - 1
	}
	return badWordList
}

// Replace 替换敏感字字符
func (s *SensitiveHelper) Replace(content string, replaceChar string, repeat bool, matchType int) (string, error) {
	if content == "" {
		return "", &PdsBusinessException{Code: EmptyContent, Message: "请填写检测的内容"}
	}
	badWordList := s.GetBadWord(content, matchType, 0)
	if len(badWordList) == 0 {
		return content, nil
	}
	for _, badWord := range badWordList {
		hasReplacedChar := replaceChar
		if repeat {
			hasReplacedChar = s.dfaBadWordConversChars(badWord, replaceChar)
		}
		content = strings.ReplaceAll(content, badWord, hasReplacedChar)
	}
	return content, nil
}

// dfaBadWordConversChars 敏感词替换为对应长度的字符
func (s *SensitiveHelper) dfaBadWordConversChars(word string, char string) string {
	var str strings.Builder
	wordLength := utf8.RuneCountInString(word)
	for i := 0; i < wordLength; i++ {
		str.WriteString(char)
	}
	return str.String()
}

// FilterKeyword 过滤敏感词
func (s *SensitiveHelper) FilterKeyword(isFilterSensitive bool, content string) (string, error) {
	// 模拟从数据库获取关键词
	type Keyword struct {
		Keyword string
		Replace string
		Type    int
	}
	var keywords []Keyword
	// 这里应该从数据库获取，暂时模拟
	// keywords = db.Query("SELECT keyword, replace, type FROM keyword_replace")

	replaceMap := make(map[string]string)
	delMap := []string{}
	wordData := []string{}
	for _, keyword := range keywords {
		if keyword.Type == 1 {
			replaceMap[keyword.Keyword] = keyword.Replace
			wordData = append(wordData, keyword.Keyword)
		} else if keyword.Type == 2 {
			delMap = append(delMap, keyword.Keyword)
		}
	}
	helper := &SensitiveHelper{}
	helper.Init()
	var err error
	helper, err = helper.SetTree(wordData)
	if err != nil {
		return "", err
	}
	sensitiveWordGroup := helper.GetBadWord(content, 1, 0)
	for _, word := range sensitiveWordGroup {
		content, err = helper.Replace(content, replaceMap[word], false, 1)
		if err != nil {
			return "", err
		}
	}
	if isFilterSensitive {
		helper, err = helper.SetTree(delMap)
		if err != nil {
			return "", err
		}
		content, err = helper.Replace(content, "", false, 1)
		if err != nil {
			return "", err
		}
	}
	return content, nil
}
